// This file is a part of Funky C++.
// Copyright (C) 2011  Valentin David
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
#ifndef PLAYER_HH
# define PLAYER_HH

# include <jack/client.hh>
# include <string.h>
# include <jack/callback_wrapper.hh>

template <size_t N, typename Signal>
struct player {
private:
  Signal signal;
  jack::client& client;
  jack::port<>* port;

  void callback(jack_nframes_t nframes,
		jack_default_audio_sample_t* buffer) {
    ::bzero(buffer, nframes * sizeof(jack_default_audio_sample_t));
    for (jack_nframes_t n = 0; n < nframes; ++n) {
      buffer[n] = *signal;
      ++signal;
    }
  }

public:
  player(const player&) = delete;
  player(player&& other):
    signal(std::move(other.signal)),
    client(other.client),
    port(other.port) {}

  player(Signal&& signal, jack::client& client):
    signal(std::move(signal)),
    client(client),
    port(client.register_port<jack_default_audio_sample_t>("player",
							   JackPortIsOutput,
							   N)) {
    port->set_callback(jack::fun(this, &player::callback));
  }

  player(const Signal& signal, jack::client& client):
    signal(signal),
    client(client),
    port(client.register_port<jack_default_audio_sample_t>("player",
							   JackPortIsOutput,
							   N)) {
    port->set_callback(jack::fun(this, &player::callback));
  }

  ~player() {
    delete port;
  }
};

template <size_t N, typename S, typename Signal = typename std::decay<S>::type>
player<N, Signal> make_player(S&& s, jack::client& c) {
  return player<N, Signal>(std::forward<S>(s), c);
}

#endif
